import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Not, Repository } from 'typeorm';
import { Insertable, Kysely, sql, Updateable } from 'kysely';
import { InjectKysely } from 'nestjs-kysely';
import { DB, Users } from '@app/db';

import { UserEntity, UserStatus } from '@app/entities/user.entity';
import {
  IUserRepository,
  UserFindOptions,
  UserListFilter,
} from '@app/interfaces/user.interface';
import { asUuid } from '@app/utils/database';

const columns = [
  'id',
  'email',
  'createdAt',
  'isAdmin',
  'shouldChangePassword',
  'deletedAt',
  'oauthId',
  'updatedAt',
  'storageLabel',
  'name',
  'status',
] as const;

@Injectable()
export class UserRepository implements IUserRepository {
  constructor(
    @InjectRepository(UserEntity)
    private userRepository: Repository<UserEntity>,
    @InjectKysely() private db: Kysely<DB>,
  ) {}

  async get(
    userId: string,
    options: UserFindOptions,
  ): Promise<UserEntity | null> {
    options = options || {};
    return this.userRepository.findOne({
      where: { id: userId },
      withDeleted: options.withDeleted,
    });
  }

  async getAdmin(): Promise<UserEntity | null> {
    return this.userRepository.findOne({ where: { isAdmin: true } });
  }

  async getByEmail(
    email: string,
    withPassword?: boolean,
  ): Promise<UserEntity | null> {
    let builder = this.userRepository
      .createQueryBuilder('user')
      .where({ email });

    if (withPassword) {
      builder = builder.addSelect('user.password');
    }

    return builder.getOne();
  }

  async getByStorageLabel(storageLabel: string): Promise<UserEntity | null> {
    return this.userRepository.findOne({ where: { storageLabel } });
  }

  async getByOAuthId(oauthId: string): Promise<UserEntity | null> {
    return this.userRepository.findOne({ where: { oauthId } });
  }

  async getDeletedUsers(): Promise<UserEntity[]> {
    return this.userRepository.find({
      withDeleted: true,
      where: { deletedAt: Not(IsNull()) },
    });
  }

  async getList({ withDeleted }: UserListFilter = {}): Promise<UserEntity[]> {
    return this.userRepository.find({
      withDeleted,
      order: {
        createdAt: 'DESC',
      },
    });
  }

  create(user: Partial<UserEntity>): Promise<UserEntity> {
    return this.save(user);
  }

  update(id: string, user: Partial<UserEntity>): Promise<UserEntity> {
    return this.save({ ...user, id });
  }

  async restore(id: string): Promise<UserEntity> {
    await this.db
      .updateTable('users')
      .set({ status: UserStatus.ACTIVE, deletedAt: null })
      .where('users.id', '=', id)
      .execute();
    const user = await this.db
      .selectFrom('users')
      .select(columns) // 确保 columns 包含你需要的字段（如 id/email/createdAt 等）
      .where('users.id', '=', id)
      .executeTakeFirst();

    return user as UserEntity;
  }

  async delete(user: UserEntity, hard?: boolean): Promise<UserEntity> {
    return hard
      ? this.userRepository.remove(user)
      : this.userRepository.softRemove(user);
  }

  private async save(user: Partial<UserEntity>) {
    const { id } = await this.userRepository.save(user);
    return this.userRepository.findOneOrFail({
      where: { id },
      withDeleted: true,
    });
  }
}
